#include "stdio.h"
#include "plat.h"
#include "elnet.h"
#include "el_netif.h"
#include "el_ipv4.h"
#include "el_nbuf.h"
#include "timer.h"
#include "el_udp.h"
#include "bitmap.h"
#include "el_ether.h"
#include "el_icmpv4.h"
#include "socket.h"
#include <stdlib.h>
#include <time.h>

pcap_t * netif;
netif_t * netif_eth0;
uint8_t fake_data[5000] = {1};

struct pcap_netif_t{
    pcap_t * netif;
    struct pcap_pkthdr * header;    /* 数据包头 */
    const u_char * packet_data;     /* 数据载荷 */
    sys_mutex_t lock;
    sys_sem_t sem;
    sys_sem_t ready_recv;//只有一个同步接收可能会出问题，再加一个同步信号，用于准备接收，先不用，因为没环境测试//20250115
};

DWORD thread1(LPVOID args) {
    nbuf_t * nbuf_udp = NULL;
	plat_printf("thread1 is running\n");
    ip4addr_t dest;
    ipv4_str2ipaddr("192.168.1.202",&dest);
	// while (1) {
    //     if(NET_ERR_OK == generate_base_packet(&nbuf_udp,(void *)fake_data,sizeof(fake_data))){
    //         udp_out(&dest,&netif_eth0->ipaddr,20003,20003,nbuf_udp);
    //     }
    //     // Sleep(10);
	// }
	return 1;
}

DWORD thread2(LPVOID args) {
    nbuf_t * nbuf_udp1 = NULL;
	plat_printf("thread2 is running\n");
    ip4addr_t dest1;
    ipv4_str2ipaddr("192.168.1.201",&dest1);
	while (1) {
        if(NET_ERR_OK == generate_base_packet(&nbuf_udp1,(void *)fake_data,sizeof(fake_data))){
            udp_out(&dest1,&netif_eth0->ipaddr,20004,20004,nbuf_udp1);
        }
        // Sleep(10);
	}
	return 1;
}
DWORD netif0_packet_recv(LPVOID args)
{
    int res;
    netif_t * netif = (netif_t *)args;
    struct pcap_netif_t * pcap_netif = (struct pcap_netif_t *)(netif->priv_args);
    do{
        sys_mutex_lock(pcap_netif->lock);
        while((res = pcap_next_ex(pcap_netif->netif, &pcap_netif->header, &pcap_netif->packet_data)) >= 0)  
        {
            if (res == 0)
                break;
            if(pcap_netif->header->len > 1514)
            {
                plat_printf("recv len > 1514!\r\n");
                break;
            }
            sys_sem_release(pcap_netif->sem);
            break;
        }
        sys_mutex_unlock(pcap_netif->lock);
    }while(1);

	return 1;
}

DWORD netif0_packet_handler(LPVOID args)
{
    netif_t * netif = (netif_t *)args;
    struct pcap_netif_t * pcap_netif = (struct pcap_netif_t *)(netif->priv_args);

    nbuf_t * nbuf;
    while(1){
        sys_sem_take(pcap_netif->sem, 0xffffffff);
        sys_mutex_lock(pcap_netif->lock);
        if(nbuf_alloc(&nbuf, pcap_netif->header->len) == NET_ERR_OK){
            if(nbuf_write(nbuf, (void *)pcap_netif->packet_data, pcap_netif->header->len) == NET_ERR_NOK){
                plat_printf("why pcap_netif->header->len changed?!\r\n");
            }
            sys_mutex_unlock(pcap_netif->lock);
            nbuf_acc_reset(nbuf);
        }
        else{
            sys_mutex_unlock(pcap_netif->lock);
            plat_printf("recv and nbuf alloc err!\r\n");
            continue;
        }

        netif_recv_queue_post( netif, nbuf, 0xffffffff);
        netif_in(netif);
    }
    return 1;
}

DWORD netif0_packet_handler2(LPVOID args)
{
    netif_t * netif = (netif_t *)args;
    struct pcap_netif_t * pcap_netif = (struct pcap_netif_t *)(netif->priv_args);

    nbuf_t * nbuf;
    while(1){
        sys_sem_take(pcap_netif->sem, 0xffffffff);
        sys_mutex_lock(pcap_netif->lock);
        if(nbuf_alloc(&nbuf, pcap_netif->header->len) == NET_ERR_OK){
            if(nbuf_write(nbuf, (void *)pcap_netif->packet_data, pcap_netif->header->len) == NET_ERR_NOK){
                plat_printf("why pcap_netif->header->len changed?!\r\n");
            }
            sys_mutex_unlock(pcap_netif->lock);
            nbuf_acc_reset(nbuf);
        }
        else{
            sys_mutex_unlock(pcap_netif->lock);
            plat_printf("recv and nbuf alloc err!\r\n");
            continue;
        }

        netif_recv_queue_post( netif, nbuf, 0xffffffff);
        netif_in(netif);
    }
    return 1;
}

DWORD netif0_packet_handler3(LPVOID args)
{
    netif_t * netif = (netif_t *)args;
    struct pcap_netif_t * pcap_netif = (struct pcap_netif_t *)(netif->priv_args);

    nbuf_t * nbuf;
    while(1){
        sys_sem_take(pcap_netif->sem, 0xffffffff);
        sys_mutex_lock(pcap_netif->lock);
        if(nbuf_alloc(&nbuf, pcap_netif->header->len) == NET_ERR_OK){
            if(nbuf_write(nbuf, (void *)pcap_netif->packet_data, pcap_netif->header->len) == NET_ERR_NOK){
                plat_printf("why pcap_netif->header->len changed?!\r\n");
            }
            sys_mutex_unlock(pcap_netif->lock);
            nbuf_acc_reset(nbuf);
        }
        else{
            sys_mutex_unlock(pcap_netif->lock);
            plat_printf("recv and nbuf alloc err!\r\n");
            continue;
        }

        netif_recv_queue_post( netif, nbuf, 0xffffffff);
        netif_in(netif);
    }
    return 1;
}

net_err_t sys_netif_open(netif_t * netif, void * args)
{
    struct pcap_netif_t * pcap_netif = malloc(sizeof(struct pcap_netif_t));
    if( pcap_netif == NULL )
        return NET_ERR_NOK;

    pcap_netif->sem = sys_sem_create(0);
    if( pcap_netif->sem == NULL ){
        free(pcap_netif);
        return NET_ERR_NOK;
    }

    pcap_netif->lock = sys_mutex_create();
    if( pcap_netif->lock == NULL ){
        free(pcap_netif);
        sys_sem_destroy(pcap_netif->sem);
        return NET_ERR_NOK;
    }
    pcap_netif->netif = sys_netif_Initialise();
    if(pcap_netif->netif == NULL){
        sys_sem_destroy(pcap_netif->sem);
        sys_mutex_destroy(pcap_netif->lock);
        free(pcap_netif);
        return NET_ERR_NOK;
    }

    netif->priv_args = (void *)pcap_netif;
    return NET_ERR_OK;
}
net_err_t ether5_send(netif_t * netif, void * data_buff, uint16_t len)
{
    struct pcap_t * pacap_netif = ((struct pcap_netif_t *)(netif->priv_args))->netif;
    pcap_sendpacket((pcap_t *)pacap_netif, (const u_char *)data_buff, (int)len);
    return NET_ERR_OK;
}

netif_ll_ops_t neiif_ether5_ll_ops = {
    .open = sys_netif_open,
    .send = ether5_send,
};

int main(void)
{
    net_start();
    ip4addr_t gateway;
    ipv4_str2ipaddr("192.168.1.1", &gateway);
    netif_eth0 = netif_add("if0", "192.168.1.105", "255.255.255.0", &gateway, LINKER_TYPE_ETHER, &neiif_ether5_ll_ops);
    sys_thread_t handle1 = sys_thread_create(thread1, NULL);
    sys_thread_t handle2 = sys_thread_create(thread2, NULL);
    sys_thread_t handle3 = sys_thread_create(netif0_packet_recv, (void *)netif_eth0);
    sys_thread_t handle4 = sys_thread_create(netif0_packet_handler, (void *)netif_eth0);
    sys_thread_t handle5 = sys_thread_create(netif0_packet_handler2, (void *)netif_eth0);
    sys_thread_t handle6 = sys_thread_create(netif0_packet_handler3, (void *)netif_eth0);
    sys_thread_t handle[5] = { handle1, handle2, handle3, handle4 };
    WaitForMultipleObjects(4, handle, TRUE, INFINITE);

	return 0;
}
